﻿using System;
using System.Collections.Generic;
using Inovout.Cloud.DataStore.Models;
using Inovout.Cloud.DataStore.Utility;
using Inovout.Cloud.Models;
using Inovout.Runtime;
using Inovout.Services;
using NHibernate.Criterion;
using Inovout.Cloud.Namespace.Services;
using Inovout.Cloud.Namespace.Models;
using Inovout.Cloud.DataStore.Repositories;

namespace Inovout.Cloud.DataStore.Services
{
    /// <summary>
    /// 数据库
    /// </summary>
    public class DatabaseService : RepositoryService<Database>, IDatabaseService
    {

        private MongoDbClient mongoDbClient;
        protected MongoDbClient MongoDbClient
        {
            get
            {
                if (mongoDbClient == null)
                {
                    mongoDbClient = new MongoDbClient(ComponentRegistry.Resolve<IApplication>().Settings["MongoDbConnectionString"].ToString());
                }

                return mongoDbClient;
            }
        }

        protected DatabaseRepository DatabaseRepository
        {
            get
            {
                return (DatabaseRepository)base.Repository;
            }
        }

        /// <summary>
        /// 创建数据库
        /// </summary>
        /// <param name="database">数据库信息</param>
        /// <returns>数据库信息</returns>
        public Database CreateDatabase(Database database)
        {
            if (database == null || String.IsNullOrEmpty(database.Name) || database.Project == null)
            {
                return null;
            }

            Inovout.Cloud.DataStore.Services.DatabaseService databaseService = (Inovout.Cloud.DataStore.Services.DatabaseService)ComponentRegistry.Resolve<Inovout.Cloud.DataStore.Services.IDatabaseService>();

            //在namespaceDatabase不存在，必须在namespace 中创建  
            if (databaseService.Exists(database.Name))
            {
                Node node = new Node() { Category = NodeCategories.DataSource, Path = database.Name };
                NodeService nodeService = (NodeService)ComponentRegistry.Resolve<INodeService>();
                nodeService.Save(node);
            }

            //如果数据库已经存在
            Database db = FindByName(database.Project, database.Name);
            if (db != null)
            {
                return db;
            }


            this.MongoDbClient.CreateDatabase(database.Name);

            base.Create(database);

            //查找刚才创建的数据库
            db = FindByName(database.Project, database.Name);
            return db;

        }

        /// <summary>
        /// 删除数据库
        /// </summary>
        /// <param name="database">数据库</param>
        public void DropDatabase(Database database)
        {
            if (database == null)
            {
                return;
            }

            DatabaseRepository.Delete(database);

            //删除Mongodb中的数据库
            this.MongoDbClient.DropDatabase(database.Name);


        }

        /// <summary>
        /// 删除数据库
        /// </summary>
        /// <param name="project">数据库所属项目</param>
        /// <param name="databaseName">数据库名</param>
        public void DropDatabaseByName(Project project, string databaseName)
        {
            if (!String.IsNullOrEmpty(databaseName))
            {
                Database db = FindByName(project, databaseName);
                if (db != null)
                {
                    bool isSuccess = this.MongoDbClient.DropDatabase(databaseName);
                    if (isSuccess)
                    {
                        //先删除数据库的所有表
                        //ITableService tableService = ComponentRegistry.Resolve<ITableService>();
                        //tableService.DropAllTables(db);

                        //再删除数据库
                        base.Delete((Object)db.Id);
                    }
                }
            }
        }

        /// <summary>
        /// 取得某个项目下的所有数据库信息
        /// </summary>
        /// <param name="project">项目信息</param>
        /// <returns>某个项目的所有数据库信息</returns>
        public IEnumerable<Database> FindAllByProject(Project project)
        {
            return base.Repository.FindAll(Restrictions.Eq("Project.Id", project.Id));
        }

        /// <summary>
        /// 取得所有的数据库信息
        /// </summary>
        /// <returns>所有的数据库信息</returns>
        public IEnumerable<Database> GetAllDatabases()
        {
            return base.Repository.FindAll();
        }

        /// <summary>
        /// 取得某个数据库信息
        /// </summary>
        /// <param name="project">项目信息</param>
        /// <param name="databaseName">数据库名</param>
        /// <returns>数据库信息</returns>
        public Database FindByName(Project project, string databaseName)
        {
            return base.Repository.Find(Restrictions.Eq("Project.Id", project.Id),
                                        Restrictions.Eq("Name", databaseName).IgnoreCase());

        }

        /// <summary>
        /// 取得某个数据库信息
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns>数据库信息</returns>
        public Database FindByName(string databaseName)
        {
            return base.Repository.Find(Restrictions.Eq("Name", databaseName).IgnoreCase());

        }

        /// <summary>
        /// 删除某个项目的所有数据库
        /// </summary>
        /// <param name="project"></param>
        public void DropAllDatabases(Project project)
        {
            if (project == null)
            {
                return;
            }

            IEnumerable<Database> dataBases = FindAllByProject(project);
            if (dataBases == null)
            {
                return;
            }

            foreach (Database database in dataBases)
            {
                DropDatabase(database);
            }
        }

        /// <summary>
        /// 判断数据库是否存在
        /// </summary>
        /// <param name="category">namespace</param>
        /// <param name="path">数据库地址</param>
        public bool Exists(string path)
        {
            //namespace中是否已存在
            NodeService nodeService = (NodeService)ComponentRegistry.Resolve<INodeService>();
            if (nodeService.Exists(NodeCategories.DataSource, path))
            {
                //不存在
                return true;
            }
            else
            {
                return false;
            }

        }
    }
}
